package Dispacher;

import Communication.AddressMachine;
import Dispacher.GUIServidor;
import Communication.InterfazReceptorMensajes;
import Communication.Message;
import java.net.InetAddress;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.ArrayList;
import javax.swing.JFrame;

public class Dispatcher extends UnicastRemoteObject implements
        InterfazReceptorMensajes {

    private static GUIServidor ventana;
    private AddressMachine mine;
    private Registry registro;
    private ArrayList<AddressMachine> conexiones;
    private static int port = 3232;

    public Dispatcher() throws RemoteException {
        try {
            ventana.anadirEntradas("************Dispatcher************");
            this.mine = new AddressMachine("Dispatcher", (InetAddress.getLocalHost()).toString(), port);
            this.conexiones = new ArrayList<AddressMachine>();
        } catch (Exception e) {
            throw new RemoteException("No se puede obtener la direccion IP.");
        }
        ventana.anadirEntradas("Conexion establecida por...\nEsta direccion=" + mine.getIp() + ", y puerto=" + mine.getPort());
        try {
            registro = LocateRegistry.createRegistry(port);
            registro.rebind("rmiServidor", this);
        } catch (RemoteException e) {
            throw e;
        }
    }

    public Message recibirMensaje(Message texto) throws RemoteException {
        String nick = texto.getFrom().getNick();
        String body = "";
        int type = 6;
        if (texto.getType() == Message.REGISTER) {
            if (this.registrarMaquina(texto.getFrom())) {
                type = Message.SUCCESS;
            }
        } else {
            if (texto.getType() == Message.LOOKUP) {
                int pos = this.buscarMaquina(texto.getNickTo());
                if (pos != -1) {
                    AddressMachine temp = this.conexiones.get(pos);
                    body = temp.getIp() + " " + temp.getPort();
                    type = Message.SUCCESS;
                } else {
                    type = Message.FAIL;
                    body = "No se encontro usuario con nick " + texto.getNickTo();
                }
            } else {
                if (texto.getType() == Message.UNREGISTER) {
                    int pos = this.buscarMaquina(texto.getNickTo());
                    if (pos != -1) {
                        this.conexiones.remove(pos);
                        type = Message.SUCCESS;
                    } else {
                        type = Message.FAIL;
                        body = "No se pudo desregistrar " + texto.getNickTo();
                    }
                }
            }
        }
        return new Message(nick, this.mine,  body, type);
    }

    private int buscarMaquina(String nick) {
        int pos = -1;
        for (int i = 0; i <
                this.conexiones.size(); i++) {
            if (this.conexiones.get(i).getNick().equals(nick)) {
                pos = i;
                i =
                        this.conexiones.size();
            }

        }
        return pos;
    }

    private boolean registrarMaquina(AddressMachine machine) {
        int pos = this.buscarMaquina(machine.getNick());
        boolean res = false;
        if (pos == -1) {
            res = true;
            this.conexiones.add(machine);
            ventana.anadirEntradas("Se registro el usuario " + machine.getNick());
        } else {
            ventana.anadirEntradas("No se pudo registrar usuario, ya se encuentra registrado usuario con nombre" + machine.getNick());
        }
        return res;
    }

    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        ventana =
                new GUIServidor();
        ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        try {
            new Dispatcher();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}
